Whisper API + ChatGPTで議事録作成するLINEボットを作ってみた
作ったもの
ユーザーがLINEのトーク画面から音声ファイルを送ると、議事録が返信されます。以下のスクショはクラスメソッドがYoutubeに出している動画(15分でわかるクラスメソッド)の冒頭3分間程度の音声データを渡してみた結果です。
https://www.youtube.com/watch?v=IgBqV7joJ0E
議事録の内容には間違った内容が書かれている場合もあったため注意が必要です。機密情報なども渡してはいけません。3分間ほどの音声で返信が得られるまでに30秒ほどかかりました。
処理の流れ
Whisper APIとChatGPTの他にLINE Messaging APIも利用しています。処理の流れは、
- LINEボットにトーク画面から音声ファイルを送ると、webhookを通してLambda関数が呼び出される。
- Lambda関数上で、LINE Messaging APIを使ってユーザーが送ってきた音声データを取得、一時ファイルとして保存
- そのファイルをWhisper APIに渡して音声データを文字起こし
- 文字起こししたテキストデータからChatGPTが議事録作成してLINEで返信
という流れです。インフラはLambda + API Gatewayで、AWS CDKを使って構築しました。
手元で動かす際はline-whisper/.envの作成と、Lambdaのパッケージをinstallする必要があります。
# line-whisper/.env
LINE_CHANNEL_ACCESS_TOKEN='LINEチャネルアクセストークン'
LINE_CHANNEL_SECRET='LINEチャネルシークレット'
OPENAI_API_KEY='OpenAI API key'
cd line-whisper/lambda && pip install -r requirements.txt -t lambda/python
プロジェクトの説明
cdk initでCDKプロジェクトを作成して、stack作成のコード(line-whisper/lib)とLambdaのコード(line-whisper/lambda)を追加しました。
mkdir line-whisper && cd line-whisper
cdk init --language python
CDKではスタック作成のコードもpythonで書きました。プロジェクトの構成は以下のようになっています。
line-whisper
├── lib (stack作成のコード)
├── lambda
│ ├── src (lambdaで実行されるコード)
│ └── python (lambdaで利用する外部ライブラリ)
└── ...
Lambdaで実行しているコードの抜粋と説明です。
# line-whisper/lambda/src/lineWebhook.py
...
# API keyを環境変数から読み込み
LINE_CHANNEL_ACCESS_TOKEN = os.environ["LINE_CHANNEL_ACCESS_TOKEN"]
LINE_CHANNEL_SECRET = os.environ["LINE_CHANNEL_SECRET"]
OPENAI_API_KEY = os.environ["OPENAI_API_KEY"]
...
# 成功時とエラー時のレスポンス
okResponse = {
"statusCode": 200,
...
errorResponse = {
"statusCode": 400,
...
mimeTypeToExtension = {"audio/x-m4a": "m4a", "audio/mpeg3": "mp3", "video/mp4": "mp4"}
def lambda_handler(event, context):
signature = event["headers"]["x-line-signature"]
# リクエストボディ取得
body = event["body"]
try:
# 署名検証とwebhookの処理
handler.handle(body, signature)
except InvalidSignatureError:
return errorResponse
return okResponse
# 音声、動画が送られてきた時の処理
@handler.add(MessageEvent, message=(AudioMessage, FileMessage, VideoMessage))
def handle_audio_message(line_event):
# メッセージIDを使って音声、動画データの取得
message_content = line_bot_api.get_message_content(line_event.message.id)
# ファイル形式(拡張子)を取得できないため、MIMEタイプから拡張子に変換
extension = mimeTypeToExtension[message_content.content_type]
# 一時ファイルの作成
with tempfile.TemporaryDirectory() as tmp_dir:
tmp_file = os.path.join(tmp_dir, f"{line_event.message.id}.{extension}")
with open(tmp_file, "wb") as fd:
for chunk in message_content.iter_content():
fd.write(chunk)
audio_file = open(tmp_file, "rb")
# whisperを使って音声をテキストに変換
transcript = openai.Audio.transcribe("whisper-1", audio_file)
# whisperから得られたテキストをChatGPTで要約
completion = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": """渡された文章に見出しをつけたり、箇条書きにして議事録を作成して下さい"""},
{"role": "user", "content": transcript.text},
],
)
gpt_response_text = completion.choices[0].message.content
# ChatGPTからのレスポンスを返信として送る
line_bot_api.reply_message(
line_event.reply_token, TextSendMessage(text=gpt_response_text)
)
LINE DevelopersでBot用のチャネル作成も必要です。作成後に「Messaging API設定」タブを押してチャネルアクセストークンを取得、「チャネル基本設定」タブからチャネルシークレットを取得して、環境変数としてenvファイルの作成をします。Whisper APIも利用するのでOpenAIのSECRET KEYも必要です。自分は直接envファイルを作成しましたが、AWS Systems Managerパラメータストアなどを使うとより安全にAPI Keyの管理ができると思います。
詰まった箇所
Lambdaレイヤー
line-whisper/lambda/python
(このディレクトリ名がpython以外だとLambda上で認識されない)
音声データの受け取り方
OpenAIの無料枠
OpenAIでは同じ電話番号で複数アカウント作成しても2つ目以降のアカウントは、無料枠がもらえません。自分は最初個人のメアドで登録していて、その後会社のメアドでも登録したので、会社のメアドでは無料枠が付与されませんでした。API keyを取得しにいく時なんで無料枠がないんだろうと思ってました。